using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.IO;
using System.Diagnostics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using System.Xml;


namespace Arcade_Machine
{
    /// <summary>
    /// This is the main type for your game
    /// notes
    /// images for the consoles must be located in the folder arcade machine exe is in
    /// all other resources should be in C:/arcade resources/
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        Texture2D BackgroundTexture;
        Texture2D MainConsoleText;
        Texture2D PrevConsoleText;
        Texture2D NextConsoleText;
        Texture2D BlankText;

        SpriteFont TitleFont;
        SpriteFont ConsoleTitleFont;
        SpriteFont SecondaryConsoleTitleFont;

        Rectangle BackgroundRect;
        Rectangle ConsoleSelect;
        Rectangle PrevConsoleSelect;
        Rectangle NextConsoleSelect;

        SoundEffect Beep;

        ArrayList ConsoleList = new ArrayList();
        ArrayList GamesList = new ArrayList();

        enum GameStates {Console, Game, None};
        GameStates CurrentState;

        string MainConsoleName = " ";
        string PrevConsoleName = " ";
        string NextConsoleName = " ";

        string MainProductionYear = " ";
        string PrevProductionYear = " ";
        string NextProductionYear = " ";

        string ArcadeDirectory = "C:/Arcade Resources/";
        string ConsoleName = "";

        int counter = 0;
        GamePadCapabilities caps;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            graphics.IsFullScreen = true;
            graphics.PreferredBackBufferHeight = 800;
            graphics.PreferredBackBufferWidth = 600;
            graphics.ApplyChanges();
            Content.RootDirectory = "Content";
            
                caps = GamePad.GetCapabilities(PlayerIndex.One);

            
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            // TODO: Add your initialization logic here
            BackgroundTexture = Content.Load<Texture2D>("Background");
            MainConsoleText = Content.Load<Texture2D>("DefaultTexture");
            PrevConsoleText = Content.Load<Texture2D>("DefaultTexture");
            NextConsoleText = Content.Load<Texture2D>("DefaultTexture");
            BlankText = Content.Load<Texture2D>("DefaultTexture");

            TitleFont = Content.Load<SpriteFont>("SpriteFont1");
            ConsoleTitleFont = Content.Load<SpriteFont>("SpriteFont2");
            SecondaryConsoleTitleFont = Content.Load<SpriteFont>("SpriteFont3");
            BackgroundRect = new Rectangle(0, 0, GraphicsDevice.Viewport.Width, GraphicsDevice.Viewport.Height);
            ConsoleSelect = new Rectangle(400, 250, 350, 175);
            PrevConsoleSelect = new Rectangle(500, 100, 200, 100);
            NextConsoleSelect = new Rectangle(500, 475, 200, 100);
            Beep = Content.Load<SoundEffect>("Beep");
            CurrentState = GameStates.Console;
            base.Initialize();
            
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);
            LoadConsoles(); //Load Your Consoles
            LoadforUpdate(); //Draw Initially
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            Type();

            // TODO: Add your update logic here

            base.Update(gameTime);
        }

        public void LoadforUpdate()
        {
            if (CurrentState == GameStates.Console)
            {
                Consoles currentcon;
                currentcon = (Consoles)ConsoleList[counter];
                using (Stream stream = File.OpenRead(ArcadeDirectory + currentcon.GetImageFileName()))
                {
                    MainConsoleText = Texture2D.FromStream(GraphicsDevice, stream);
                } 
                MainConsoleName = currentcon.GetGameName();
                MainProductionYear = currentcon.GetYear();
            }
            else if(CurrentState == GameStates.Game)
            {
                Games currentgam;
                currentgam = (Games)GamesList[counter];
                using (Stream stream = File.OpenRead(ArcadeDirectory + ConsoleName + "/" + currentgam.GetImageFileName()))
                {
                    MainConsoleText = Texture2D.FromStream(GraphicsDevice, stream);
                } 

                MainConsoleName = currentgam.GetGameName();
                MainProductionYear = currentgam.GetYear();
            }



            if (counter < (ConsoleList.Count - 1))
            {
                if (CurrentState == GameStates.Console)
                {
                    Consoles Nextcon;
                    Nextcon = (Consoles)ConsoleList[counter + 1];
                    using (Stream stream = File.OpenRead(ArcadeDirectory + Nextcon.GetImageFileName()))
                    {
                        NextConsoleText = Texture2D.FromStream(GraphicsDevice, stream);
                    } 
                    NextConsoleName = Nextcon.GetGameName();
                    NextProductionYear = Nextcon.GetYear();
                }
                else if (CurrentState == GameStates.Game)
                {
                    Games Nextgam;
                    Nextgam = (Games)GamesList[counter + 1];
                    using (Stream stream = File.OpenRead(ArcadeDirectory + ConsoleName + "/" + Nextgam.GetImageFileName()))
                    {
                        NextConsoleText = Texture2D.FromStream(GraphicsDevice, stream);
                    } 
                    NextConsoleName = Nextgam.GetGameName();
                    NextProductionYear = Nextgam.GetYear();
                }
            }
            else
            {

                    NextConsoleText = BlankText;
                    NextConsoleName = " ";
                    NextProductionYear = " ";
            }

            if (counter > 0)
            {
                if (CurrentState == GameStates.Console)
                {
                    Consoles Prevcon;
                    Prevcon = (Consoles)ConsoleList[counter - 1];
                    using (Stream stream = File.OpenRead(ArcadeDirectory + Prevcon.GetImageFileName()))
                    {
                        PrevConsoleText = Texture2D.FromStream(GraphicsDevice, stream);
                    } 
                    PrevConsoleName = Prevcon.GetGameName();
                    PrevProductionYear = Prevcon.GetYear();
                }
                else if (CurrentState == GameStates.Game)
                {
                    Games Prevgam;
                    Prevgam = (Games)GamesList[counter - 1];
                    using (Stream stream = File.OpenRead(ArcadeDirectory + ConsoleName + "/" + Prevgam.GetImageFileName()))
                    {
                        PrevConsoleText = Texture2D.FromStream(GraphicsDevice, stream);
                    }
                    PrevConsoleName = Prevgam.GetGameName();
                    PrevProductionYear = Prevgam.GetYear();
                }
            }
            else
            {
                PrevConsoleText = BlankText;
                PrevConsoleName = " ";
                PrevProductionYear = " ";
            }
        }

        public void LoadConsoles()
        {
            XmlDocument File = new XmlDocument(); //New XMLDocument
            File.Load("C:/Arcade Resources/Consoles.xml"); //Load Highscores
            XmlNodeList ConsoleListNodes = File.GetElementsByTagName("console");
            foreach (XmlNode node in ConsoleListNodes) //For Each Person
            {
                XmlElement Console = (XmlElement)node; //Each Console
                Consoles CurrrentConsole = new Consoles();
                string ConsoleName = Console.GetElementsByTagName("Name")[0].InnerText; //Read in the Console Name
                CurrrentConsole.SetGameName(ConsoleName);

                string CreationYear = Console.GetElementsByTagName("Year")[0].InnerText; //Read in Year Console was Created
                CurrrentConsole.SetYear(CreationYear);

                string ConsolePictureName = Console.GetElementsByTagName("ImageName")[0].InnerText; //Read in the Location for the Images
                CurrrentConsole.SetImageFileName(ConsolePictureName);

                string ConsoleGameListfile = Console.GetElementsByTagName("GamesList")[0].InnerText; //UnUsed Atm
                CurrrentConsole.SetGameIniFileName(ConsoleGameListfile);

                ConsoleList.Add(CurrrentConsole); //Add to Object to the List
            }
        }

        public void LoadGames(string Filename)
        {
            XmlDocument File = new XmlDocument(); //New XMLDocument
            string Filename2 = "C:/Arcade Resources/" + ConsoleName + "/" + ConsoleName + ".xml";
            File.Load(Filename2); //Load Highscores
            XmlNodeList ConsoleListNodes = File.GetElementsByTagName("console");
            foreach (XmlNode node in ConsoleListNodes) //For Each Person
            {
                XmlElement Console = (XmlElement)node; //Each Console
                Games CurrrentGame = new Games();
                string LocalConsoleName = Console.GetElementsByTagName("Name")[0].InnerText; //Read in the Console Name
                CurrrentGame.SetGameName(LocalConsoleName);

                string CreationYear = Console.GetElementsByTagName("Year")[0].InnerText; //Read in Year Console was Created
                CurrrentGame.SetYear(CreationYear);

                string ConsolePictureName = Console.GetElementsByTagName("ImageName")[0].InnerText; //Read in the Location for the Images
                CurrrentGame.SetImageFileName(ConsolePictureName);

                string ConsoleGameListfile = Console.GetElementsByTagName("ROM")[0].InnerText; //UnUsed Atm
                CurrrentGame.SetROMName(ConsoleGameListfile);

                GamesList.Add(CurrrentGame); //Add to Object to the List
            }
        }


        #region TypingNames

        Keys[] keysToCheck = new Keys[] {
    Keys.U, Keys.V, Keys.W, Keys.X, Keys.Y,
    Keys.Z, Keys.Back, Keys.Enter, Keys.Escape, Keys.Up, Keys.Down};

        KeyboardState currentKeyboardState;
        KeyboardState lastKeyboardState;

        public void Type()
        {
            currentKeyboardState = Keyboard.GetState(); //Set Current Keyboard State
            foreach (Keys key in keysToCheck) //For Each Key
            {
                if (checkkeypress(key)) //Checks Key Hasnt Been Pressed more than once
                {
                    typeletter(key); //Add Keys to String
                    break; //Leaves Loop
                }
            }
            lastKeyboardState = currentKeyboardState;
        }

        private void typeletter(Keys key)
        {
            switch (key) //For Each Key
            {
                case Keys.Enter:
                    if (CurrentState == GameStates.Console)
                    {

                        Consoles currentcon;
                        currentcon = (Consoles)ConsoleList[counter];
                        ConsoleName = currentcon.GetGameName();
                        counter = 0;
                        LoadGames(MainConsoleName);

                        System.Threading.Thread.Sleep(600);
                        CurrentState = GameStates.Game;
                        LoadforUpdate();
                    }
                    else if (CurrentState == GameStates.Game)
                    {
                        Games currentgam;
                        currentgam = (Games)GamesList[counter];
                      
                        Process.Start(ArcadeDirectory + ConsoleName + "/Emulator/" + currentgam.GetROMName());
                        CurrentState = GameStates.Console;
                        LoadforUpdate();
                    }
                    break;

                case Keys.Z:
                    this.Exit();
                    break;

                case Keys.Up:
                    if (counter < (ConsoleList.Count - 1))
                        counter++;
                    Beep.Play();
                    LoadforUpdate();
                    break;

                case Keys.Down:
                    if (counter > 0)
                        counter--;
                    Beep.Play();
                    LoadforUpdate();
                    break;
            }
        }

        private bool checkkeypress(Keys theKey)
        {
            return lastKeyboardState.IsKeyDown(theKey) && currentKeyboardState.IsKeyUp(theKey); //If key is not the same key, to prevent printing same key multiple times
        }

        #endregion


        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);
            spriteBatch.Begin();
            spriteBatch.Draw(BackgroundTexture, BackgroundRect,Color.White);
      
                //Main
                spriteBatch.Draw(MainConsoleText, ConsoleSelect, Color.White);
                spriteBatch.DrawString(ConsoleTitleFont, MainConsoleName, new Vector2(50, 320), Color.Yellow);
                spriteBatch.DrawString(SecondaryConsoleTitleFont, MainProductionYear, new Vector2(50, 350), Color.Yellow);
                //Previous
                spriteBatch.Draw(PrevConsoleText, PrevConsoleSelect, new Color(255, 255, 255, (byte)MathHelper.Clamp(0, 0, 0)));
                spriteBatch.DrawString(SecondaryConsoleTitleFont, PrevConsoleName, new Vector2(225, 120), Color.Yellow);
                spriteBatch.DrawString(SecondaryConsoleTitleFont, PrevProductionYear, new Vector2(250, 150), Color.Yellow);
                //Next
                spriteBatch.Draw(NextConsoleText, NextConsoleSelect, new Color(255, 255, 255, (byte)MathHelper.Clamp(0, 0, 0)));
                spriteBatch.DrawString(SecondaryConsoleTitleFont, NextConsoleName, new Vector2(225, 470), Color.Yellow);
                spriteBatch.DrawString(SecondaryConsoleTitleFont, NextProductionYear, new Vector2(250, 500), Color.Yellow);
               
            spriteBatch.DrawString(TitleFont, "Select A Console:", new Vector2(220, 10), Color.Yellow); //Title
            spriteBatch.End();
            // TODO: Add your drawing code here
            
            base.Draw(gameTime);
        }
    }
}
